#ifndef _UIEDIT_H
#define _UIEDIT_H

//////////////////////////////////////////////////////////////////////////


class DUI_API CTestDlg:public CWindowUI
{
public:
	UIBEGIN_MSG_MAP
		//EVNET_ID_HANDLER(UINOTIFY_CLICK, L"test", OnClickBtnTest)
		UIEND_MSG_MAP
		static CTestDlg* GetInstance();
	LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
	static LPCTSTR GetDlgName(){ return _T("test"); }
	//bool OnClickBtnTest(TNotifyUI* pNotify);
private:
	CTestDlg();	
	virtual ~CTestDlg();
	static CTestDlg *m_pDlg;
};

///////////////////////////////////////////////////////////
///////////    CMyEdit Class
///////////////////////////////////////////////////////////

typedef	  BYTE			MyBool;
#ifdef     UNICODE
#define	  MYTRUE		2
#define	  MYFALSE	0
#else
#define	  MYBOOL		BYTE
#define	  MYTRUE		1
#define	  MYFALSE	0
#endif

class DUI_API CMultiLineEdit:public CLabelUI
{
public:
	typedef struct tagCHARPOS
	{
		unsigned  LineIndex;
		unsigned  CharIndex;
	}CharPos;
	struct LINEINFO
	{
		unsigned CharsCount;
		MyBool bParaEnd;
		LINEINFO(unsigned nCount = 0, MyBool bFlag = MYFALSE)
		{
			CharsCount = nCount;
			bParaEnd = bFlag;
		}
	};
	typedef LINEINFO *LPLINEINFO;
	typedef vector<LPLINEINFO>  CLineInfoArray;
	enum ADJUSTMODE
	{
		INSERT_ONLY,
		DEL_AND_INSERT
	};
public:
	CMultiLineEdit();
	virtual ~CMultiLineEdit();
public:
	virtual void Render(HDC &hDestDC, RECT &rcPaint);
	virtual bool Event(TEventUI& event);
	virtual void Init();
	virtual void OnSize(const RECT& rectRegion);
	virtual bool Activate();
	virtual void SetAttribute(LPCTSTR lpszName, LPCTSTR lpszValue);
	static CControlUI* CreateObject();
public:
	BOOL CreateCaret(int nWidth, int nHeight);
	BOOL SetCaretPos(int x, int y);
	BOOL ShowCaret();
	BOOL HideCaret();
	BOOL DestroyCaret();
	void SetSelEndPoint();
public:
	void GetSel(tstring &str) const;
	void Copy() const;
	void Paste();
	void Clear();
	LPCTSTR GetText();
	void SetText(LPCTSTR lpszText);
	void SetReadOnly(bool bReadOnly);
protected:
	void OnKeyDown(UINT nChar, UINT nFlags);
	void OnChar(UINT nChar, UINT nFlags);
	void OnLButtonDown(UINT nFlags, POINT pt);
	void OnRButtonDown(UINT nFlags, POINT pt);
	void OnLButtonUp(UINT nFlags, POINT pt);
	void OnLButtonDblClk(UINT nFlags, POINT pt);
	void OnMouseMove(UINT nFlags, POINT pt);
protected:
	void CharPos2Point(const CharPos &pos, POINT &pt) const;
	void Point2CharPos(const POINT &pt, CharPos &pos) const;
	void CharPos2Index(const CharPos &pos, unsigned &nIndex) const;
	void Index2CharPos(const unsigned &nIndex, CharPos &pos) const;
private:
	void CalLhAcw();
	void Insert(LPCTSTR lpszText);
	bool DelSelRange();
	bool EnsureSelEndVisible();
	void LeftSelEnd();
	void RightSelEnd();
	void UpSelEnd();
	void DownSelEnd();

	void AdjustFromLineToParaEnd(const unsigned LineNum, const ADJUSTMODE mode = DEL_AND_INSERT);
	void AdjustAllLineInfo();
	int CutStringForOneLine(HDC hDC, const TCHAR *lpszText) const;
	unsigned FindNextCrlfLine(unsigned nStartLine) const;
	int FindPrevCrlfLine(unsigned nStartLine) const;
	void RemoveLineInfo(unsigned nStartLine, unsigned nCount);
	void RemoveLineInfo(unsigned nStartLine = 0);

	void DrawRange(HDC hDC, const CharPos &pos1, const CharPos &pos2);
	BOOL TextOut(HDC hDC, int x, int y, LPCTSTR lpszText, int c);
	void InvalidateRect(LPRECT lpRect, BOOL bFlag = FALSE);
	RECT GetInsertReDrawRect(const CharPos &beforeChangePos, 
		const CharPos &afterChangePos, const bool bAddLine) const;
	RECT GetDeleteReDrawRect(const CharPos &beforeChangePos,
		const CharPos &afterChangePos, const bool bSubLine) const;
	RECT GetSelectReDrawRect() const;
	void GetClientRect(RECT &rc);
private:
	HWND						m_hParentWnd;
	HCURSOR					m_hCursor;
	CLineInfoArray			m_lineInfoArray;
	CharPos					m_cpSelBegin;
	CharPos					m_cpSelEnd;
	CharPos					m_cpPrevSelEnd;
	int								m_nFirstVisibleLine;
	int								m_nLineHeight;
	int								m_nAveCharWidth;
	unsigned					m_uClientWidth;
	unsigned					m_uClientHeight;
	HFONT						m_hFont;
	COLORREF				m_clrInputBk;
	COLORREF				m_clrText;
	COLORREF				m_clrSelBk;
	COLORREF				m_clrSelText;
	CScrollbarUI            *m_pVerticalScrollbar;
	bool							m_bReadOnly;
	bool							m_bCaret;
	bool							m_bKillFocus;
	bool							m_bTransparent;
	bool							m_bInit;
};


class DUI_API CEditUI:public CLabelUI
{
public:
	CEditUI();
	~CEditUI();
protected:
	void OnKeyDown(UINT nChar, UINT nFlags);
	void OnChar(UINT nChar, UINT nFlags);
	void OnLButtonDown(UINT nFlags, POINT pt);
	void OnRButtonDown(UINT nFlags, POINT pt);
	void OnLButtonUp(UINT nFlags, POINT pt);
	void OnLButtonDblClk(UINT nFlags, POINT pt);
	void OnMouseMove(UINT nFlags, POINT pt);
public:
	virtual void Render(HDC &hDestDC, RECT &rcPaint);
	virtual bool Event(TEventUI& event);
	virtual void SetAttribute(LPCTSTR lpszName, LPCTSTR lpszValue);
	static CControlUI* CreateObject();
	virtual void Init();
	virtual void OnSize(const RECT& rectRegion);
public:
	void Copy();
	void Paste();
	void GetSel(tstring &str) const;
	void  SetText(LPCTSTR lpszText);
	LPCTSTR GetText();
	void SelectAllText();
	inline void SetReadOnly(bool bReadOnly = true);
	inline bool IsReadOnly() const;
	inline void SetPassword(bool bPassword);
public:
	BOOL CreateCaret(int nWidth, int nHeight);
	BOOL SetCaretPos(int x, int y);
	BOOL ShowCaret();
	BOOL HideCaret();
	BOOL DestroyCaret();
	void SetSelEndPoint();
private:
	void Index2Point(const unsigned index, POINT &pt) const;
	void Point2Index(POINT pt, unsigned &index) const;
	BOOL EnsureSelEndVisible();
	void CalLhAcw();
	int Insert(LPCTSTR lpszText);
	int DelSelRange();
	inline void LeftSelEnd();
	inline void RightSelEnd();
	void SetPrevSelEndInfo(int offsetPixels); //used for insert, delete
	void SetPrevSelEndInfo();//used for setPoint
	unsigned GetCharsCounts(HDC hDC, const int pixels) const;
	int GetCharsPixels(HDC hDC, const unsigned nCounts) const;	
	unsigned GetLeftClientWidthIndex(HDC hDC, unsigned pos) const;
	unsigned GetRightClientWidthIndex(HDC hDC, unsigned pos) const;
	RECT GetInsertReDrawRect(unsigned beforeInsertPos) const;
	RECT GetDeleteReDrawRect() const;
	RECT GetSelectReDrawRect(unsigned beforeMovePos) const;
	void GetClientRect(RECT &rc);
public:
	void DrawRange(HDC hDC, const unsigned &index1, const unsigned &index2);
	BOOL TextOut(HDC hDC, int x, int y, LPCTSTR lpszText, int c);
private:
	HWND						m_hParentWnd;
	HFONT						m_hFont;
	HCURSOR					m_hCursor;
	unsigned					m_uSelBegin;
	unsigned					m_uSelEnd;
	int								m_nFirstVisiblePixel;
	int								m_nTextPixel;
	unsigned					m_nClientWidth;
	int								m_nAveCharWidth;
	int								m_nLineHeight;
	int								m_cy;
	COLORREF				m_clrInputBk;
	COLORREF				m_clrText;
	COLORREF				m_clrSelBk;
	COLORREF				m_clrSelText;
	unsigned					m_uPrevSelEnd;
	int								m_nPrevSelEndPixel;
	bool							m_bCaret;
	bool							m_bReadOnly;
	bool							m_bPassword;
	tstring						m_strPasswdText;
	TCHAR						m_tcPassChar;
	int								m_nPasswdCharWidth;
	tstring						m_strEmptyTips;
	COLORREF				m_clrEmptyTipsText;
	bool							m_bTransparent;
	bool							m_bInit;
protected:
	bool							m_bKillFocus;
};

#endif